package com.tiancheng.trade.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tiancheng.trade.commom.core.data.Result;
import com.tiancheng.trade.commom.core.exception.error.BusinessErrorInfoEnum;
import com.tiancheng.trade.commom.web.feign.MerchantFeignService;
import com.tiancheng.trade.commom.web.model.request.PayWayListQueryReq;
import com.tiancheng.trade.commom.web.model.request.PaymentPayWayQueryRequest;
import com.tiancheng.trade.commom.web.model.request.QueryOrderMerchantReqVO;
import com.tiancheng.trade.commom.web.model.response.PaymentPayWayQueryResponse;
import com.tiancheng.trade.commom.web.model.response.QueryOrderMerchantResVO;
import com.tiancheng.trade.commom.web.model.response.UnifiedOrderResVO;
import com.tiancheng.trade.commom.web.model.response.MerchantPaymentChannelBO;
import com.tiancheng.trade.commom.web.feign.PaymentFeignService;
import com.tiancheng.trade.order.configuration.OrderCenterConfigProperties;
import com.tiancheng.trade.order.mapper.OrderMapper;
import com.tiancheng.trade.order.model.Order;
import com.tiancheng.trade.order.service.SubOrderService;
import com.tiancheng.trade.order.util.cache.OrderCache;
import com.tiancheng.trade.order.util.helper.OrderIdHelper;
import com.tiancheng.trade.order.vo.app.CashierVO;
import com.tiancheng.trade.order.vo.open.order.OpenOrderPayVO;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: likailun
 * @Description:
 * @Date: create in 2023/6/9 17:05
 */
@Slf4j
@Service
public class BaseOrderPayService extends ServiceImpl<OrderMapper, Order> {
    @Autowired
    protected OrderMapper orderMapper;
    @Resource
    protected MerchantFeignService merchantFeignService;
    @Autowired
    protected SubOrderService subOrderService;
    @Resource
    protected PaymentFeignService paymentFeignService;
    @Resource
    protected OrderIdHelper orderIdHelper;
    @Resource
    protected OrderCenterConfigProperties orderCenterConfigProperties;

    /**
     * 查询支付渠道信息
     *
     * @param merchantCods 商户号
     * @return
     */
    protected List<MerchantPaymentChannelBO> getPayChannelMapsByMerchantCodes(Set<String> merchantCods) {
        String merchantCodsStr = merchantCods.stream().collect(Collectors.joining(","));
        final String merchantKey = merchantCodsStr.replaceAll(",", "");
        final Optional<List<MerchantPaymentChannelBO>> merchantInfo = OrderCache.getCacheMerchantInfo(merchantKey);
        if (merchantInfo.isPresent()) {
            return merchantInfo.get();
        }
        Result<List<MerchantPaymentChannelBO>> result = merchantFeignService.findPaymentChannelByMerchantCodes(merchantCodsStr);
        BusinessErrorInfoEnum.ORDER_CREATE_CHANNEL_ERROR.assertIsTrue(result.getRet() == 0 && result.getErrorCode() == 0);
        log.info("根据商户号获取支渠道信息：{}", result);
        OrderCache.cacheMerchantInfo(merchantKey, result.getData());
        return result.getData();
    }


    /**
     * 查询支付商户渠道信息
     *
     * @param params 下单商户信息
     * @return
     */
    protected List<QueryOrderMerchantResVO> getOrderMerchants(QueryOrderMerchantReqVO params) {
        List<QueryOrderMerchantResVO> merchants = new ArrayList<>();
        List<String> nullCacheMerchant = new ArrayList<>();
        for (String merchantCode : params.getMerchantCods()) {
            Optional<QueryOrderMerchantResVO> cachePayMerchantInfo = OrderCache.getCachePayMerchantInfo(params.getOrgPaymentChannelId(), merchantCode);
            if (cachePayMerchantInfo.isPresent()) {
                merchants.add(cachePayMerchantInfo.get());
            } else {
                nullCacheMerchant.add(merchantCode);
            }
        }
        if (CollectionUtils.isEmpty(nullCacheMerchant)) {
            return merchants;
        }
        params.setMerchantCods(nullCacheMerchant);
        final Result<List<QueryOrderMerchantResVO>> result = merchantFeignService.queryOrderMerchant(params);
        BusinessErrorInfoEnum.ORDER_CREATE_CHANNEL_ERROR.assertIsTrue(result.getRet() == 0 && CollectionUtils.isNotEmpty(result.getData()));
        log.info("根据商户号获取支渠道信息：{}", result);
        for (QueryOrderMerchantResVO datum : result.getData()) {
            merchants.add(datum);
            OrderCache.cachePayMerchantInfo(params.getOrgPaymentChannelId(), datum.getMerchantCode(), datum);
        }
        return merchants;
    }


    /**
     * 根据客户端信息判断是否需要矫正支付渠道，某些场景在创建时无法确定客户端信息，需要在收银台做处理
     *
     * @param cashierVO  查询收银台参数
     * @param conditions 查询主订单条件
     * @param orders     主订单集合
     * @param payChannel 原主订单支付渠道
     * @return 校验后的支付渠道编码
     */
    protected String checkPayChannelByClientVersion(CashierVO cashierVO, QueryWrapper conditions, List<Order> orders, String payChannel) {
        return payChannel;
    }


    /**
     * 获取收银台支付列表
     *
     * @param orgPayChannelId    支付渠道编码
     * @param paymentChannelCode 支付渠道id
     * @param payScene           支付场景
     * @param payWay             支付方式
     * @return
     */
    public List<PaymentPayWayQueryResponse> getPayWayListByPayChannel(@NotNull Long orgPayChannelId, String paymentChannelCode, String payScene, String payWay) {
        Optional<List<PaymentPayWayQueryResponse>> cashier = OrderCache.getCashier(orgPayChannelId, payScene, payWay);
        if (cashier.isPresent()) {
            log.info("缓存取支付渠道信息");
            return cashier.get();
        }
        final PayWayListQueryReq payWayListQueryReq = new PayWayListQueryReq();
        payWayListQueryReq.setPaymentChannelId(orgPayChannelId);
        payWayListQueryReq.setPaymentChannelCode(paymentChannelCode);
        payWayListQueryReq.setPayScene(payScene);
        payWayListQueryReq.setPayWay(payWay);
        Result<List<PaymentPayWayQueryResponse>> result = paymentFeignService.getPayWayByPaySceneChannelId(payWayListQueryReq);
        log.info("支付渠道:{},支付方式:{}", paymentChannelCode, result);
        BusinessErrorInfoEnum.ORDER_CASHIER_PAY_WAY_FAIL.assertIsTrue(result.getRet() == 0 && result.getErrorCode() == 0);
        BusinessErrorInfoEnum.ORDER_CASHIER_PAY_WAY_EMPTY.assertIsTrue(CollectionUtils.isNotEmpty(result.getData()));
        OrderCache.cacheCashier(orgPayChannelId, payScene, payWay, result.getData());
        return result.getData();
    }


    /**
     * 获取缓存中的预支付信息
     *
     * @param orderPayVO
     * @param orders
     * @return
     */
    protected Optional<String> getCachePrePayInfo(String uid, OpenOrderPayVO orderPayVO, List<Order> orders, String batchId) {
        //TreeSet<String> orderIds = orders.stream().map(Order::getOrderId).collect(Collectors.toCollection(TreeSet::new));
        String cacheUniqueKey = orderIdHelper.getUniqueIdByOrderIds(uid, orders.stream().map(Order::getOrderId).collect(Collectors.toList()), orderPayVO.getPayWay(), orderPayVO.getPayScene(), batchId);
        // 判断订单是否重复支付，直接从缓存拿预支付信息
        Optional<UnifiedOrderResVO> prePayInfo = OrderCache.getPrePayInfo(cacheUniqueKey);
        return prePayInfo.map(UnifiedOrderResVO::getPayInfo);
    }


}
